import { BadRequestException, Injectable } from '@nestjs/common';
import { PrismaService } from 'nestjs-prisma';
import { LoginDto } from './common/dto/login.dto';
import { decode } from './common/utils/crypto';
import { UserEntity } from './core/user/entities/user.entity';
import { AuthDto } from './common/dto/auth.dto';
import { FileConfig, SecurityConfig } from './config/config.interface';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { UserService } from './core/user/user.service';

@Injectable()
export class AppService {
  constructor(
    private jwtService: JwtService,
    private configService: ConfigService,
    private prisma: PrismaService,
    private userService: UserService,
  ) {}

  async doLogin(form: LoginDto) {
    const user = await this.prisma.user.findUnique({
      where: {
        username: form.username,
      },
      select: {
        id: true,
        name: true,
        username: true,
        password: true,
        role: true,
        iv: true,
        key: true,
      },
    });
    if (user) {
      const password = decode(user.password, user.key, user.iv);
      if (password === form.password) {
        return this.generateTokens(user);
      } else {
        throw new BadRequestException('用户名或密码！');
      }
    } else {
      throw new BadRequestException('用户不存在！');
    }
  }

  async generateTokens(payload: UserEntity): Promise<AuthDto> {
    delete payload.password;
    delete payload.iv;
    delete payload.key;

    const accessToken = this.getAccessToken(payload);
    return {
      accessToken: accessToken,
      refreshToken: this.getRefreshToken(payload),
    };
  }

  getAccessToken(payload: UserEntity) {
    return this.jwtService.sign(payload);
  }

  getRefreshToken(payload: UserEntity) {
    const securityConfig = this.configService.get<SecurityConfig>('security');

    return this.jwtService.sign(payload, {
      secret: this.configService.get('JWT_REFRESH_SECRET'),
      expiresIn: securityConfig.expiresIn,
    });
  }

  async getProfile(id: string) {
    return this.prisma.user.findUnique({
      where: {
        id,
      },
      select: {
        id: true,
        name: true,
        username: true,
        remark: true,
        mobile: true,
        role: true,
        createdAt: true,
        updatedAt: true,
        avatar: true,
      },
    });
  }

  async init() {
    const count = await this.prisma.user.count({
      where: {
        username: 'admin',
      },
    });
    if (count === 0) {
      await this.userService.create({
        role: 'admin',
        username: 'admin',
        password: 'admin123!~',
      });
    }

    return 'ok';
  }
}
